/*
 * LDIR
 *
 * LDIR, a GPS cartography application built for Let's Do It Romania eco
 * campaign.
 * Copyright (C) 2010 Genera Software <office@generasoftware.com>
 *
 * http://generasoftware.com/
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 */
#include "gpsutils.h"
#include "gpsnavidecorator.h"
#include <e32math.h>
#include <eikspane.h>
#include <aknappui.h>

void GPSUtils::AppendFormatLongitude( TDes& aBuf, TReal64 aLongitude )
    {
    _LIT(KFormatE, "E");
    _LIT(KFormatW, "W");

    AppendFormatCoordinate( aBuf, aLongitude );
    if ( aBuf.Length() > 0 )
        {
        if ( aLongitude > 0.0 )
            {
            aBuf.Append( KFormatE );
            }
        else
            {
            aBuf.Append( KFormatW );
            }
        }
    }

void GPSUtils::AppendFormatLatitude( TDes& aBuf, TReal64 aLatitude )
    {
    _LIT(KFormatN, "N");
    _LIT(KFormatS, "S");

    AppendFormatCoordinate( aBuf, aLatitude );
    if ( aBuf.Length() > 0 )
        {
        if ( aLatitude > 0.0 )
            {
            aBuf.Append( KFormatN );
            }
        else
            {
            aBuf.Append( KFormatS );
            }
        }
    }

void GPSUtils::AppendFormatCoordinate( TDes& aBuf, TReal64 aCoordinate )
    {
    _LIT(KFormatDDDMMSSSS, "%d\xb0%02d'%02d\.%02d\"");

    if ( !Math::IsNaN( aCoordinate ) )
        {
        TReal64 workReal( 0.0 );
        TReal coordinateAbs = Abs( aCoordinate );
        TInt32 degreeInt( 0 );
        TInt32 degreeFracInt( 0 );
        TInt32 minInt( 0 );
        TInt32 minFracInt( 0 );
        TInt32 secondInt( 0 );
        TInt32 secondFracInt( 0 );
        TInt err = Math::Int( degreeInt, coordinateAbs );
        if ( err != KErrNone )
            {
            return;
            }
        err = Math::Frac( workReal, coordinateAbs );
        if ( err != KErrNone )
            {
            return;
            }
        err = Math::Int( degreeFracInt, workReal * 100000.0 );
        if ( err != KErrNone )
            {
            return;
            }
        TReal minReal = workReal * 60.0;
        err = Math::Int( minInt, minReal );
        if ( err != KErrNone )
            {
            return;
            }
        err = Math::Frac( workReal, minReal );
        if ( err != KErrNone )
            {
            return;
            }
        err = Math::Int( minFracInt, workReal * 10000.0 );
        if ( err != KErrNone )
            {
            return;
            }
        TReal secordReal = workReal * 60.0;
        err = Math::Int( secondInt, secordReal );
        if ( err != KErrNone )
            {
            return;
            }
        err = Math::Frac( workReal, secordReal );
        if ( err != KErrNone )
            {
            return;
            }
        err = Math::Int( secondFracInt, workReal * 100.0 );
        if ( err != KErrNone )
            {
            return;
            }
        aBuf.AppendFormat( KFormatDDDMMSSSS, degreeInt, minInt, secondInt,
            secondFracInt );
        }
    }

void GPSUtils::AppendFormatAltitude( TDes& aBuf, TReal32 aAltitude )
    {
    AppendFormatFeetsMetres( aBuf, aAltitude );
    }

void GPSUtils::AppendFormatSpeed( TDes& aBuf, TReal32 aSpeed )
    {
    AppendFormatKmph( aBuf, aSpeed );
    }

void GPSUtils::AppendFormatSpeed( TDes& aBuf, TReal32 aSpeed,
    TReal32 aVerticalSpeed )
    {
    _LIT(KFormatVerticalHead, "(V. ");
    _LIT(KFormatVerticalTail, ")");

    AppendFormatKmph( aBuf, aSpeed );
    if ( !Math::IsNaN( aVerticalSpeed ) )
        {
        aBuf.Append( KFormatVerticalHead );
        AppendFormatKmph( aBuf, aVerticalSpeed );
        aBuf.Append( KFormatVerticalTail );
        }
    }

void GPSUtils::AppendFormatCourse( TDes& aBuf, TReal32 aTrueCourse,
    TReal32 aHeading )
    {
    _LIT(KFormatCourse, "%.2f");

    if ( !Math::IsNaN( aTrueCourse ) )
        {
        aBuf.AppendFormat( KFormatCourse, aTrueCourse );
        }
    else if ( !Math::IsNaN( aHeading ) )
        {
        aBuf.AppendFormat( KFormatCourse, aHeading );
        }
    }

void GPSUtils::AppendFormatAccuracy( TDes& aBuf, TReal32 aAccuracy )
    {
    AppendFormatFeetsMetres( aBuf, aAccuracy );
    }

void GPSUtils::AppendFormatAccuracy( TDes& aBuf, TReal32 aAccuracy,
    TReal32 aVerticalAccuracy )
    {
    _LIT(KFormatVerticalHead, "(V. ");
    _LIT(KFormatVerticalTail, ")");

    AppendFormatFeetsMetres( aBuf, aAccuracy );
    if ( !Math::IsNaN( aVerticalAccuracy ) )
        {
        aBuf.Append( KFormatVerticalHead );
        AppendFormatFeetsMetres( aBuf, aVerticalAccuracy );
        aBuf.Append( KFormatVerticalTail );
        }
    }

void GPSUtils::AppendFormatDoP( TDes& aBuf, TReal32 aDoP )
    {
    _LIT(KFormatDoP, "%.2f");

    if ( !Math::IsNaN( aDoP ) )
        {
        aBuf.AppendFormat( KFormatDoP, aDoP );
        }
    }

void GPSUtils::AppendFormatDoP( TDes& aBuf, TReal32 aDoP, TReal32 aVerticalDoP )
    {
    _LIT(KFormatVerticalHead, "(V. ");
    _LIT(KFormatVerticalTail, ")");
    _LIT(KFormatDoP, "%.2f");

    if ( !Math::IsNaN( aDoP ) )
        {
        aBuf.AppendFormat( KFormatDoP, aDoP );
        }
    if ( !Math::IsNaN( aVerticalDoP ) )
        {
        aBuf.Append( KFormatVerticalHead );
        aBuf.AppendFormat( KFormatDoP, aVerticalDoP );
        aBuf.Append( KFormatVerticalTail );
        }
    }

void GPSUtils::AppendFormatSatelliteNum( TDes& aBuf, TInt8 aInView, TInt8 aUsed )
    {
    _LIT(KFormatNum, "%d/%d");

    aBuf.AppendFormat( KFormatNum, aUsed, aInView );
    }

void GPSUtils::AppendFormatTimeDateL( TDes& aBuf, const TTime& aTime,
    const TBool aConvLocalFlag )
    {
    _LIT(KFormat, "%-B%:0%J%:1%T%:2%S%:3%+B %D%M%Y%/0%1%/1%2%/2%3%/3");
    AppendFormatTimeStampL( aBuf, KFormat, aTime, aConvLocalFlag );
    }

void GPSUtils::AppendFormatDateTimeL( TDes& aBuf, const TTime& aTime,
    const TBool aConvLocalFlag )
    {
    _LIT(KFormat, "%D%M%Y%/0%1%/1%2%/2%3%/3 %-B%:0%J%:1%T%:2%S%:3%+B");
    AppendFormatTimeStampL( aBuf, KFormat, aTime, aConvLocalFlag );
    }

void GPSUtils::AppendFormatTimeStampL( TDes& aBuf, const TDesC& aFormat,
    const TTime& aTime, const TBool aConvLocalFlag )
    {
    TTime tmLocal = aTime;
    //    if ( aConvLocalFlag )
    //        {
    //        RTz tzServer;
    //        User::LeaveIfError( tzServer.Connect() );
    //        CleanupClosePushL( tzServer );
    //        TInt err = tzServer.ConvertToLocalTime( tmLocal );
    //        CleanupStack::PopAndDestroy(); // tzServer
    //        if ( err != KErrNone )
    //            return;
    //        }
    TBuf<32> buf;
    tmLocal.FormatL( buf, aFormat );
    aBuf.Append( buf );
    }

CGPSNaviDecorator* GPSUtils::PushGPSNaviDecoratorL()
    {
    CEikStatusPane
        * sp =
            static_cast<CAknAppUi*> ( CEikonEnv::Static()->EikAppUi() )->StatusPane();
    CAknNavigationControlContainer* naviPane =
        static_cast<CAknNavigationControlContainer*> ( sp->ControlL( TUid::Uid(
            EEikStatusPaneUidNavi ) ) );
    if ( naviPane->Top() )
        {
        naviPane->Pop();
        }
    CGPSNaviDecorator* gpsNavi = CGPSNaviDecorator::NewLC();
    gpsNavi->SetContainerWindowL( *naviPane );
    naviPane->PushL( *gpsNavi );
    CleanupStack::Pop();
    return gpsNavi;
    }

void GPSUtils::PopGPSNaviDecoratorL( CAknNavigationDecorator* naviDecorator )
    {
    CEikStatusPane
        * sp =
            static_cast<CAknAppUi*> ( CEikonEnv::Static()->EikAppUi() )->StatusPane();
    CAknNavigationControlContainer* naviPane =
        static_cast<CAknNavigationControlContainer*> ( sp->ControlL( TUid::Uid(
            EEikStatusPaneUidNavi ) ) );
    naviPane->Pop( naviDecorator );
    }

void GPSUtils::AppendFormatFeetsMetres( TDes& aBuf, TReal32 aValue )
    {
    _LIT(KFormatMetricNoNaN, "%.1f m");

    if ( !Math::IsNaN( aValue ) )
        {
        aBuf.AppendFormat( KFormatMetricNoNaN, aValue );
        }
    }

void GPSUtils::AppendFormatKmph( TDes& aBuf, TReal32 aValue )
    {
    _LIT(KFormatMetricNoNaN, "%.2f km/h");

    if ( !Math::IsNaN( aValue ) )
        {
        aBuf.AppendFormat( KFormatMetricNoNaN, ( aValue * 3.6 ) );
        }
    }

void GPSUtils::SetNaN( TReal32& aValue )
    {
    TRealX realNaN;
    realNaN.SetNaN();
    realNaN.GetTReal( aValue );
    }
void GPSUtils::SetNaN( TReal64& aValue )
    {
    TRealX realNaN;
    realNaN.SetNaN();
    realNaN.GetTReal( aValue );
    }
